layui.use(['layer', 'table', 'carousel', 'upload', 'element', 'util', 'form', 'tree'], function () {
  var element = layui.element,
    layer = layui.layer,
    util = layui.util,
    form = layui.form,
    $ = layui.$,
    tree = layui.tree


  var ws;
  var is_hooking = 0;
  var is_pause = 0;
  var is_refresh_auto = 0;
  var exeAndHook_default = {
    "exePath": "E:\\资料\\计算机\\软件安全\\课设\\TestInitialNullForStudent\\InjectDll\\Release\\sample_server.exe",
    "hookPath": "E:\\资料\\计算机\\软件安全\\课设\\TestInitialNullForStudent\\InjectDll\\Release\\TestConsole.exe"
  };
  var exeAndHook_info = {
    "exePath": [],
    "hookPath": []
  };
  var pageName = ["进程信息", "MessageBox", "堆操作", "网络通信", "文件操作", "注册表"];
  var pageName_2 = ["堆操作问题", "网络通信行为", "文件操作异常", "注册表可疑操作", "内存拷贝监测与关联"]
  var pageId = ["process", "MessageBox", "heap", "socket", "file", "Registry"]
  var nowPage = 0; // 0为显示进程信息，1为MessageBox，2为堆操作
  var nowPage_2 = 0;
  var process = {};
  var MessageBox = {
    'MessageBoxA': [],
    'MessageBoxW': []
  };
  var heap = {
    "HeapCreate": [],
    "HeapDestory": [],
    "HeapFree": [],
    "about_analysis": {
      "about": {
        "name": "涉及的堆地址"
      },
      "analysis": {
        "heapSet": [],
        "[HeapCreate]重复创建堆": [],
        "[Unknown]释放或销毁了未知的堆": [],
        "[HeapDestory]销毁了未创建的堆": [],
        "[HeapFree]释放了未创建的堆": []
      }
    }
  };
  var socket = {
    "WSASocketW": [],
    "bind": [],
    "WSASend": [],
    "WSAConnect": [],
    "WSARecv": [],
    "about_analysis": {
      "about": {
        "name": "涉及的IP:端口"
      },
      "analysis": {
        "[ANALYSIS]协议解析": [],
        "[WARNING]疑似明文传输": []
      }
    }
  };
  var file = {
    "CreateFileA": [],
    "WriteFile": [],
    "ReadFile": [],
    "OpenFile": [],
    "about_analysis": {
      "about": {
        "name": "涉及的文件夹"
      },
      "analysis": {
        "[Warning]疑似自我复制": [],
        "[Warning]修改了exe/dll/ocx": [],
        "[Warning]将数据发送到网络": []
      }
    }
  };
  var Registry = {
    "RegCreateKeyExA": [],
    "RegSetValueExA": [],
    "RegCloseKey": [],
    "RegOpenKeyExA": [],
    "RegDeleteValueA": [],
    "about_analysis": {
      "about": {
        "name": "涉及的注册表项"
      },
      "analysis": {
        "[WARNING]新增注册表项": [],
        "[WARNING]修改注册表项": [],
      }
    }
  };
  var memory = {
    "memcpy": [],
    "about_analysis": {
      "about": {
        "name": "涉及的内存块"
      },
      "analysis": {
        "[ANALYSIS]内存拷贝信息流走向": []
      }
    }
  };
  var page_info = [process, MessageBox, heap, socket, file, Registry, memory]
  var specialMapping = {
    "80000000":"HKEY_CLASSES_ROOT",
    "80000001":"HKEY_CURRENT_USER",
    "80000002":"HKEY_LOCAL_MACHINE",
    "80000003":"HKEY_USERS",
    "80000004":"HKEY_PERFORMANCE_DATA",
    "80000005":"HKEY_CURRENT_CONFIG",
    "80000006":"HKEY_DYN_DATA",
    "80000007":"HKEY_CURRENT_USER_LOCAL_SETTINGS",
    af:{
      "00000000":"AF_UNSPEC(任意协议)",
      "00000002":"AF_INET(IPv4)",
      "00000006":"AF_IPX",
      "00000016":"AF_APPLETALK",
      "00000017":"AF_NETBIOS",
      "00000023":"AF_INET6(IPv6)",
      "00000026":"AF_IRDA",
      "00000032":"AF_BTH",
    },
    type:{
      "00000001":"SOCK_STREAM(面向连接)",
      "00000002":"SOCK_DGRAM(无连接的)",
      "00000003":"SOCK_RAW",
      "00000004":"SOCK_RDM",
      "00000005":"SOCK_SEQPACKET",
    },
    protocol:{
      "00000000":"Any",
      "00000001":"IPPROTO_ICMP",
      "00000002":"IPPROTO_IGMP",
      "00000003":"BTHPROTO_RFCOMM",
      "00000006":"IPPROTO_TCP",
      "00000017":"IPPROTO_UDP",
      "00000058":"IPPROTO_ICMPV6",
      "00000113":"IPPROTO_RM",
    }
  }

  //头部事件
  util.event("lay-header-event", {
    //左侧菜单事件
    menuLeft: function (othis) {
      layer.msg("展开左侧菜单的操作", {
        icon: 0
      });
    },
    menuRight: function () {
      layer.open({
        type: 1,
        content: '<div style="padding: 15px;">处理右侧面板的操作</div>',
        area: ["260px", "100%"],
        offset: "rt", //右上角
        anim: 5,
        shadeClose: true,
      });
    },
  });

  function setHtml(typeId) {
    nowPage = typeId;
    let func_info = page_info[typeId];
    $('#func_info .layui-card-header').html(pageName[typeId]);
    let dataList = []
    $.each(func_info, function (key, record) { // key: 函数名称 record: 该函数记录
      if (key == "about_analysis") return true; // 不渲染about_analysis
      let list = []
      $.each(record, function (index, item) { // index: 记录序号 item: 该记录的函数信息
        let argChild = []
        listTitle=item.name + '[TYPE ' + item.type + '] ' + item.st;
        $.each(item.arg, function (argName, argValue) {
          if(argName=="times"){
            listTitle+=' ('+argValue+'次)'
            return true;
          }
          if(argValue=='')argValue='NULL'
          argChild.push({
            title: argName + ': ' + argValue
          });
        });
        list.push({
          title: listTitle,
          children: argChild
        })
      });
      dataList.push({
        title: key,
        spread:true,
        children: list
      });
    });
    //console.log(dataList);
    tree.render({
      elem: '#argv_tree',
      onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩
      data: dataList,
      accordion: true // 手风琴模式
    });
    $('#pro_info').css('display', 'none');
    $('#func_info').css('display', 'block');
    $('#about_analysis').css('display', 'none');
  }


  function setHtml_2(typeId) {
    nowPage_2 = typeId;
    //console.log(page_info[typeId]);
    let func_info = page_info[typeId].about_analysis;
    $('#about_name').html(func_info.about.name);
    let aboutList = []
    $.each(func_info.about, function (key, val) {
      if (key == "name") return true; // 不将name渲染进树形组件
      let recordList = []
      $.each(val, function (index, item) { // 将记录以title: xxx的形式存入recordList列表，方便树形组件的渲染
        recordList.push({
          title: item
        });
      });
      aboutList.push({
        title: key,
        children: recordList
      })
    });
    tree.render({
      elem: '#about_tree',
      onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩
      data: aboutList
    });

    let dataList = []
    $.each(func_info.analysis, function (key, val) {
      if (key == "name") return true; // 过滤一些特殊信息
      let analysisList = []
      $.each(val, function (index, item) {
        analysisList.push({
          title: item,
        })
      });
      dataList.push({
        title: key,
        spread: true,
        children: analysisList
      })
    });
    tree.render({
      elem: '#analysis_tree',
      onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩
      data: dataList,
      accordion: true // 手风琴模式
    });
    $('#pro_info').css('display', 'none');
    $('#func_info').css('display', 'none');
    $('#about_analysis').css('display', 'block');
  }

  // 左侧导航栏点击事件
  element.on("nav(nav)", function (data) {
    if(!is_hooking)layer.msg('Hook未开启 无信息')
    nowPage = pageName.indexOf(data.context.innerText);
    if (nowPage !=-1) {
      nowPage_2 = -1;
    } else {
      nowPage = -1;
      nowPage_2 = pageName_2.indexOf(data.context.innerText);
      if(nowPage_2 != -1)
        nowPage_2 = nowPage_2 + 2; // 跳过前两个没对齐的
    }
    if(nowPage != -1 || nowPage_2 != -1)
    refreshPage();
  });

  
  function refreshPage(){
    $('#btn_info').css('display', 'block');
    if (nowPage > 0 )
      setHtml(nowPage);
    else if(nowPage==0){
      $('#pro_info').css('display', 'block');
      $('#btn_info').css('display', 'none');
      $('#func_info').css('display', 'none');
      $('#about_analysis').css('display', 'none');
    }
    else if (nowPage_2 != -1)
      setHtml_2(nowPage_2);
    
  }

  //自定义验证规则
  form.verify({
    path: function (value) {
      if (value.length < 2) {
        return '路径至少得2个字符';
      }
    },
    pass: [
      /^[\S]{6,12}$/, '密码必须6到12位，且不能出现空格'
    ],
    content: function (value) {
      layedit.sync(editIndex);
    }
  });

  function checkUnexpected(item, info) {
    let nowAbout = item.about_analysis.about;
    let isNew = 1;      // 记录这是否是一个新的参数
    let recordItem;     // 专门被记录的参数
    if (item == heap) recordItem = info.arg.hHeap;
    else if(item == file) {
      let lastFan=info.arg.FilePath.lastIndexOf('\\');
      if(lastFan!=-1)
        recordItem = info.arg.FilePath.substring(0,lastFan);  // 只取路径不取文件名
      else recordItem = info.arg.FilePath;
      info.arg.FileName = info.arg.FilePath.substring(lastFan+1);
    }else if(item==Registry){
      if(info.arg.hKey in specialMapping){
        info.arg.hKey=specialMapping[info.arg.hKey];
        recordItem = info.arg.lpSubKey;
      }
      else{
        recordItem = info.arg.hKey; // 不记录Open和Create这种特殊的hKey
      }
    }else if(item == socket){
      if('IP' in info.arg && 'port' in info.arg){
        info.arg.port=(parseInt(info.arg.port)).toString();
        recordItem = info.arg.IP +':'+info.arg.port;
      }
    }else if(item == memory){
      recordItem = info.arg._Src+' -> '+info.arg._Dst;
    }

    if(recordItem != undefined){
    // console.log(recordItem, nowAbout);
    // 向about字典中尝试记录recordItem
    if (recordItem in nowAbout) {
      isNew = 0;
    } else {
      nowAbout[recordItem] = []; //  将第一个参数放入about字典中(不重复插入)
    }
    let about_push = info.name;
    if(item==file)
      about_push += '(' + info.arg.FileName + ')'
    else if(info.name=='HeapFree')
      about_push += '(' + info.arg.times + '次)'
    about_push += ' ' + info.st;
    nowAbout[recordItem].push(about_push); // 记录操作和时间戳
  }
    let nowAnalysis = item.about_analysis.analysis;

    if (item == heap)       // [堆操作异常分析] recordItem 是 hHeap
    {
      if (info.name == "HeapCreate") {
        if (nowAnalysis.heapSet.indexOf(recordItem) == -1) // 检查当前记录的堆中是否存在该堆
          nowAnalysis.heapSet.push(recordItem); // 如果不存在就push
        else nowAnalysis["[HeapCreate]重复创建堆"].push(recordItem + ' ' + info.st); // 如果已存在就记录堆和时间戳
      } else if (info.name == "HeapDestory" || info.name == "HeapFree") {
        let index = nowAnalysis.heapSet.indexOf(recordItem);
        if (index != -1) // 检查当前记录的堆中是否存在该堆
          nowAnalysis.heapSet.splice(index, 1); // 如果存在就直接删除它
        else if (isNew) {
          nowAnalysis["[Unknown]释放或销毁了未知的堆"].push('[' + info.name + ']' + recordItem + ' ' + info.st); // 如果已存在就记录堆和时间戳
        } else {
          if (info.name == "HeapDestory")
            nowAnalysis["[HeapDestory]销毁了未创建的堆"].push(recordItem + ' ' + info.st); // 如果已存在就记录堆和时间戳
          else {
            nowAnalysis["[HeapFree]释放了未创建的堆"].push(recordItem + '(' + info.arg.times + '次) ' + info.st); // 如果已存在就记录堆和时间戳
        }
        }
      }
    }
    else if(item == file){  // [文件操作异常分析] recordItem 是 FilePath
      if(info.arg.FilePath == exeAndHook_info.exePath){
        nowAnalysis["[Warning]疑似自我复制"].push(info.name+' '+ info.arg.FilePath + ' ' + info.st); // 如果已存在就记录堆和时间戳
      }
      if(info.arg.lpFileType=='exe'||info.arg.lpFileType=='dll'||info.arg.lpFileType=='ocx'){
        nowAnalysis["[Warning]修改了exe/dll/ocx"].push(info.name+'('+ info.arg.FilePath + ') ' + info.st); // 如果已存在就记录堆和时间戳
      }
    }
    else if(item == socket){// [网络通信异常分析] recordItem 是 IP:port
      if(info.name == "WSASocketW"){
        info.arg.af = specialMapping.af[info.arg.af];
        info.arg.type = specialMapping.type[info.arg.type];
        info.arg.protocol = specialMapping.protocol[info.arg.protocol];
        nowAnalysis["[ANALYSIS]协议解析"].push(info.name+'('+ info.arg.af+', '+info.arg.type+', '+ info.arg.protocol + ') ' + info.st); // 如果已存在就记录堆和时间戳
      }else if('Buffers' in info.arg){
        nowAnalysis["[WARNING]疑似明文传输"].push(info.name+'('+ info.arg.Buffers + ') ' + info.st); // 如果已存在就记录堆和时间戳
        file.about_analysis.analysis["[Warning]将数据发送到网络"].push(info.name+'('+ info.arg.Buffers + ') (' + recordItem + ') ' + info.st)
      }
      
      else if(item == memory){
        //TODO
      }
    }
    // "[WARNING]新增注册表项": [],
    //     "[WARNING]修改注册表项": [],
    else if(item == Registry){// [注册表异常分析] recordItem 是 hKey
      if(info.name == "RegCreateKeyExA")
        nowAnalysis["[WARNING]新增注册表项"].push(info.name+'('+ info.arg.lpSubKey + ') ' + info.st); // 如果已存在就记录堆和时间戳
      else if(info.name == "RegOpenKeyExA")
        nowAnalysis["[WARNING]修改注册表项"].push(info.name+'('+ info.arg.lpSubKey + ') ' + info.st); // 如果已存在就记录堆和时间戳
      else if(info.name=="RegDeleteValueA" || info.name == "RegSetValueExA")
      nowAnalysis["[WARNING]修改注册表项"].push(info.name+'('+ info.arg.hKey+', '+ info.arg.lpValueName + ') ' + info.st);
    }
  }

  
  //监听提交
  form.on('submit(startHook)', function (d) {
    exeAndHook_info = form.val('hookBegin');
    let data = JSON.stringify(exeAndHook_info);
    if ("WebSocket" in window) {
      if (!is_hooking) {
        ws = new WebSocket("ws://localhost:8092/");
        //ws.binaryType = 'arraybuffer';
        ws.onopen = function () {
          // Web Socket 已连接上，使用 send() 方法发送数据
          layer.msg("success connected");
          is_hooking = 1;
          ws.send(b64Encode(data))
          ws.send(b64Encode("start hook"));
        };

        ws.onmessage = function (e) {
          console.log(b64Decode(e.data));
          var info = JSON.parse(b64Decode(e.data))
          //console.log(info);
          if("err" in info){
            layer.msg("进程打开失败，请检查路径");
              setTimeout(function(){ws.onclose();},3000);// 刷新页面
          }
          if ("EXE" in info) {
            $("#exe_info").css('visibility', 'visible');
            $('#pro_name').html(info.name);
            $('#pro_pid').html(info.id);
            $('#pro_priority').html(info.priority);
            $('#exe_path').html(d.field.exePath);
            $('#exe_size').html((parseInt(info.EXE.size)/1024).toString()+' KB');
            $('#exe_drive').html(info.EXE.drive);
            $('#thread_id').html(info.thread.id);
            $('#thread_handle').html(info.thread.handle);
            processHtml = document.getElementById('exe_info').innerHTML;
          } else if ("type" in info) {
            $.each(page_info, function (index, item) {
              if (info.name in item) {
                item[info.name].push(info); // 更新Hook到的函数信息列表
                checkUnexpected(item, info); //  检查新Hook的函数是否异常，更新异常行为，并存入about_analysis中
                if (is_refresh_auto) {
                  if (nowPage == page_info.indexOf(item)) {
                    setHtml(nowPage);
                  } else if (nowPage_2 == page_info.indexOf(item)) //TODO：因为直接刷新会使树形组件重新展开，很影响观感，所以使用按钮刷新
                    setHtml_2(nowPage_2);
                }
                return false;
              }
            });
          }

        };

        ws.onclose = function () {
          // 关闭 websocket
          if (is_hooking) {
            layer.msg("连接已关闭...");
            setTimeout(function(){location.reload();},1000);// 刷新页面
          } else {
            layer.msg("连接失败，请检查是否运行服务端");
          }
        };
      } else {
        layer.msg('Hooking has been started~');
        ws.send(b64Encode("start hook"));
      }
    } else {
      // 浏览器不支持 WebSocket
      alert("您的浏览器不支持 WebSocket!");
    }
    return false;
  });

  //按钮事件
  util.event('lay-btn', {
    setDefault: function () {
      form.val('hookBegin', exeAndHook_default);
    },
    btn_pause: function (obj) {
      if (is_hooking) {
        is_pause = !is_pause;
        if (is_pause) {
          obj.context.innerHTML = '<i class="layui-icon layui-icon-pause"></i>开始';
          ws.send(b64Encode("pause"));
        } else {
          obj.context.innerHTML = '<i class="layui-icon layui-icon-pause"></i>暂停';
          ws.send(b64Encode("start sending"));
        }
      } else {
        layer.msg('Hook 未开启');
      }
    },
    btn_close: function () {
      if (is_hooking) {
        ws.send(b64Encode("stop hook"));
        ws.close();
      } else {
        ws.send(b64Encode("stop hook"));// 为了保险起见，在is_hooking为0时也试探着向服务端断开连接
        ws.close();
        layer.msg('Hook 未连接');
      }
    },
    clearList: function () {
      if(nowPage!=-1){
        $.each(page_info[nowPage], function (key, val) {
          if(key=="about_analysis")return true;
          page_info[nowPage][key]=[];
        });
      }else if(nowPage_2!=-1){
        page_info[nowPage_2].about_analysis.about={"name":page_info[nowPage_2].about_analysis.about.name}
        $.each(page_info[nowPage_2].about_analysis.analysis, function (key, val) {
          page_info[nowPage_2].about_analysis.analysis[key]=[];
        });
      }
      refreshPage();
    },
    refresh: function () {
      refreshPage();
      layer.msg('已刷新');
    },
    refresh_auto: function (obj) {
      is_refresh_auto = !is_refresh_auto;
      if (is_refresh_auto) {
        obj.context.innerHTML = '<i class="layui-icon layui-icon-delete"></i>关闭自动刷新';
        refreshPage();
      }
      else obj.context.innerHTML = '<i class="layui-icon layui-icon-delete"></i>开启自动刷新';
    },
    reload: function () {
      //重载实例
      tree.reload('demoId1', {});
    }
  });



  function b64Encode(str) {
    return btoa(unescape(encodeURIComponent(str)));
  }

  function b64Decode(str) {
    return decodeURIComponent(escape(atob(str)));
  }



});